/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_ENTITY_H
#define M_ENTITY_H

#include "movableobject.h"
#include "movableobjectvisitor.h"
#include "subentity.h"
#include "types.h"
#include "refptr.h"
#include "shadowvolume.h"

#include <vector>
#include <map>

namespace Engine
{
	/**
	*   Class for operating with mesh instances
	*/
	class Entity: public MovableObject
	{
	public:
		friend class SubEntity;
		typedef std::vector< RefPtr<SubEntity,WeakPtrExtension> > SubEntityVector;
		typedef std::map<std::string, RefPtr<ShadowVolume,WeakPtrExtension> > ShadowVolumeMap;

		/**
		*   Constructor.
		*/
		Entity(const std::string& name, MeshPtr mesh);

		/**
		*   Destructor.
		*/
		~Entity();

		/**
		*   Retrieves the local axis-aligned bounding box for this object.
        */
        virtual const AABB& GetBoundingBox(void) const;

		/**
		*   Method for supporting visitor pattern (see scene manager).
		*/
		virtual void Accept(MovableObjectVisitor* visitor);

		/**
		*   Returns mesh associated.
		*/
		MeshPtr GetMesh();

	private:

		/**
		*   Internal method by which the movable object must add Renderable subclass instances to the rendering queue.
        */
		virtual void UpdateRenderQueue(RenderQueue* queue, RenderQueue* shadowsQueue, const std::vector<LightPtr>& lightList);


		/**
		*   Update shadow volumes with lights positons,and populate render queue
		*/
		void UpdateShadowVolumes(RenderQueue* shadowsQueue, const std::vector<LightPtr>& lightList);

	private:

		SubEntityVector m_subEntities;
		MeshPtr m_mesh;
		ShadowVolumeMap m_shadowVolumes;
	};

	/******************************************************************************************************/

	/**
	*   Factory object for creating entities
	*/
	class EntityFactory : public MovableObjectFactory
	{
	public:
		EntityFactory():m_type("Entity") {}
		~EntityFactory() {}

		/**
		*   Returns the factory type.
		*/
		virtual const std::string& GetType() const { return m_type; }

		/**
		*   Creates a new object.
		*   @param name Name of the object to create
		*   @return	An object created by the factory. The type of the object depends on	the factory.
		*/
		virtual Entity* CreateInstance( const std::string& name );
	protected:
		std::string m_type;
	};
}

#endif
